
#ifndef __U_MSG_H_
#define __U_MSG_H_



typedef struct _tag_umsg {
	struct _tag_umsg * next;
    uint16_t rsvd;
    
    uint8_t mlen;
    uint8_t type;
    uint8_t data[64];

} umsg_t;


int umsg_init( int num );


/*
 * user 调用, 获得从 host 下发来的消息.
 * 执行 syscall, 自动屏蔽其他中断.
 * 如果没有消息, 不会阻塞, 返回 NULL.
 */
static inline umsg_t * umsg_recv(void) {
  register umsg_t *pmsg __asm("r0");
  __ASM volatile("SVC #2": "=r"(pmsg) :  : "memory" );
  return pmsg;
}



/*
 * 执行 syscall.
 * 如果 usb buffer 满状态, 会临时构成单链表, 不会阻塞..
 */
static inline void umsg_send( umsg_t * pmsg )
{ 
    pmsg->data[pmsg->mlen] = pmsg->type;
    pmsg->mlen += 1;
    
    /**/
    __ASM volatile ( "MOV r0, %0; SVC #3" : : "r"(pmsg) : "memory" );
    return;
}


//
int umsg_inp_cbk( void * parg, uint8_t * ptr, int tmax );
int umsg_outp_cbk( void * parg, uint8_t * ptr, int tsiz );




/*
 * queue, fifo.
 */

typedef struct _tag_queue {
    umsg_t * tail;
    umsg_t head;
} uqueue_t;


static inline void umsg_q_init( uqueue_t * pque )
{
    pque->head.next = &(pque->head);
    pque->tail = &(pque->head);
    pque->head.rsvd = 0;
}


static inline void umsg_q_enque( uqueue_t * pque, umsg_t * pnd )
{
    pnd->next = &(pque->head);
    pque->tail->next = pnd;
    pque->tail = pnd;

    pque->head.rsvd += 1;
}


static inline umsg_t * umsg_q_deque( uqueue_t * pque )
{
    umsg_t * pnd;

    if ( pque->head.next == &(pque->head) ) {
        return NULL;
    }

    pnd = pque->head.next;    
    pque->head.next = pnd->next;
    pque->head.rsvd -= 1;

    if ( pque->head.next == &(pque->head) ) {
        pque->tail = &(pque->head);
    }

    return pnd;
}


static inline bool umsg_q_is_empty( uqueue_t * pque )
{
    if ( pque->head.next == &(pque->head) ) {
        return true;
    } else {
        return false;
    }
}


/**/
umsg_t * umsg_alloc( void );
void umsg_free( umsg_t * pnd );


#endif


